using System;
using System.Data;
using System.Web.UI;
using System.Web.UI.Design;
using System.ComponentModel;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using NBusiness.Utilities;
using System.Windows.Forms;

namespace NBusiness.Data.Web.Design
{
    /// <summary>
    /// Object providing schema information for a
    /// business object.
    /// </summary>
    [Serializable]
    public class ObjectViewSchema : IDataSourceViewSchema
    {
        private string _typeAssemblyName = string.Empty;
        private string _typeName = string.Empty;

        /// <summary>
        /// Create an instance of the object.
        /// </summary>
        /// <param name="assemblyName">The assembly containing
        /// the business class for which to generate the schema.</param>
        /// <param name="typeName">The business class for
        /// which to generate the schema.</param>
        public ObjectViewSchema(string assemblyName, string typeName)
        {
            _typeAssemblyName = assemblyName;
            _typeName = typeName;
        }

        /// <summary>
        /// Returns a list of child schemas belonging to the
        /// object.
        /// </summary>
        /// <remarks>This schema object only returns
        /// schema for the object itself, so GetChildren will
        /// always return Nothing (null in C#).</remarks>
        public IDataSourceViewSchema[] GetChildren()
        {
            List<IDataSourceViewSchema> childSchemas = new List<IDataSourceViewSchema>();
            
            Type t;
            if (Reflection.TryLoadType(_typeAssemblyName, _typeName, out t))
            {
                if (t is IHasChildren)
                {
                    IHasChildren hasChildren = t as IHasChildren;
                    foreach (Type childType in hasChildren.GetChildTypes())
                    {
                        childSchemas.Add(new ObjectViewSchema(childType.Assembly.FullName, childType.FullName));
                    }
                }
            }

            return childSchemas.ToArray();
        }
        /// <summary>
        /// Returns schema information for each property on
        /// the object.
        /// </summary>
        /// <remarks>All public properties on the object
        /// will be reflected in this schema list except
        /// for those properties where the 
        /// <see cref="BrowsableAttribute">Browsable</see> attribute
        /// is False.
        /// </remarks>
        public IDataSourceFieldSchema[] GetFields()
        {
            //System.Diagnostics.Debugger.Launch();
            List<IDataSourceFieldSchema> fields = new List<IDataSourceFieldSchema>();
            Type t;
            if (Reflection.TryLoadType(_typeAssemblyName, _typeName, out t))
            {
                if (t.BaseType.IsGenericType)
                {
                    Type lt = typeof(EntityBaseCollection<>);
                    Type gt = t.BaseType.GetGenericTypeDefinition();
                    if (gt.FullName == lt.FullName)
                    {
                        t = t.BaseType.GetGenericArguments()[0];
                    }
                }

                //System.Diagnostics.Debugger.Break();
                foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(t))
                {
                    BindableAttribute bindable = 
                        (BindableAttribute)pd.Attributes[typeof(BindableAttribute)];
                    if (bindable == null || bindable.Bindable == true)
                    {
                        fields.Add(new ObjectFieldInfo(pd));
                    }
                }
            }
            return fields.ToArray();
        }

        /// <summary>
        /// Returns the name of the schema.
        /// </summary>
        public string Name
        {
            get { return "Default"; }
        }

    }
}
